package lia.meetlucene;

/**
 * Copyright Manning Publications Co.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific lan
 */

import org.apache.log4j.Logger;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.Directory;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.FileReader;

import static lia.util.Constants.*;
import static lia.util.Utilities.*;

// From chapter 1

/**
 * This code was originally written for Erik's Lucene intro java.net article
 * 
 * @author Wenlong Meng(wenlong.meng@gmail.com)
 * @version 1.0 at 2011/08/01 for lucene 3.3.0
 */
public class Indexer {

	// local variables
	/**
	 * index writer
	 */
	private IndexWriter writer;
	/**
	 * log
	 */
	private static final Logger logger = Logger.getLogger("commonLogger");

	/**
	 * test entry
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		/*
		 * if (args.length != 2) { throw new
		 * IllegalArgumentException("Usage: java " + Indexer.class.getName() +
		 * " <index dir> <data dir>"); } String indexDir = args[0]; //1 String
		 * dataDir = args[1];
		 */// 2*/
		logger.debug("Begin: test main Indexer...");
		long start = System.currentTimeMillis();
		Indexer indexer = new Indexer(buildIndexDir("1"));
		int numIndexed = 0;
		try {
			numIndexed = indexer.index(buildDataDir("1"), new TextFilesFilter());
		} finally {
			indexer.close();
		}
		long end = System.currentTimeMillis();

		logger.debug("Indexing " + numIndexed + " files took " + (end - start)
				+ " milliseconds");
		logger.debug("End: test main Indexer!");
	}

	/**
	 * build Indexer instance: index file of indexDir
	 * 
	 * @param indexDir
	 *            A Directory is a flat list of files
	 * @throws IOException
	 */
	public Indexer(String indexDir) throws IOException {
		logger.debug("the index dir: " + indexDir);
		Directory dir = FSDirectory.open(new File(indexDir));
		IndexWriterConfig iwc = new IndexWriterConfig(LUCENE_VERSION,
				new StandardAnalyzer(LUCENE_VERSION));
		iwc.setOpenMode(OpenMode.CREATE);
		logger.debug(iwc);
		writer = new IndexWriter(dir, iwc);
		// writer = new IndexWriter(dir, //3
		// new StandardAnalyzer( //3
		// Version.LUCENE_30),//3
		// true, //3
		// IndexWriter.MaxFieldLength.UNLIMITED); //3
	}

	/**
	 * close index writer
	 * 
	 * @throws IOException
	 */
	public void close() {
		try {
			logger.debug("close index writer...");
			writer.close();
		} catch (CorruptIndexException e) {
			logger.error("close index writer error:", e);
		} catch (IOException e) {
			logger.error("close index writer error:", e);
		} // 4
	}

	/**
	 * index the file of dataDir, and filter is true
	 * 
	 * @param dataDir
	 * @param filter
	 * @return
	 * @throws Exception
	 */
	public int index(String dataDir, FileFilter filter) throws Exception {
		logger.debug("the data dir:" + dataDir);
		File[] files = new File(dataDir).listFiles();

		for (File f : files) {
			logger.debug("f:" + f.getPath() + f.getName());
			if (!f.isDirectory() && !f.isHidden() && f.exists() && f.canRead()
					&& (filter == null || filter.accept(f))) {
				indexFile(f);
			}
		}
		logger.debug("numDocs:" + writer.numDocs());
		return writer.numDocs(); // 5
	}

	/**
	 * filter files: the file that end with .txt is true
	 * 
	 * @author F.H Dragon
	 * @version 1.0 at 2011/08/03
	 */
	private static class TextFilesFilter implements FileFilter {
		public boolean accept(File path) {
			return path.getName().toLowerCase() // 6
					.endsWith(".txt"); // 6
		}
	}

	/**
	 * build doc from file f
	 * 
	 * @param f
	 * @return
	 * @throws Exception
	 */
	protected Document getDocument(File f) throws Exception {
		Document doc = new Document();
		doc.add(new Field("contents", new FileReader(f))); // 7
		doc.add(new Field("filename", f.getName(), // 8
				Field.Store.YES, Field.Index.NOT_ANALYZED));// 8
		doc.add(new Field("fullpath", f.getCanonicalPath(), // 9
				Field.Store.YES, Field.Index.NOT_ANALYZED));// 9
		return doc;
	}

	/**
	 * index file f
	 * 
	 * @param f
	 *            file
	 * @throws Exception
	 */
	private void indexFile(File f) throws Exception {
		logger.debug("Indexing " + f.getCanonicalPath());
		Document doc = getDocument(f);
		logger.debug("addDoc: " + doc);
		writer.addDocument(doc); // 10
	}
}

/*
 * #1 Create index in this directory #2 Index *.txt files from this directory #3
 * Create Lucene IndexWriter #4 Close IndexWriter #5 Return number of documents
 * indexed #6 Index .txt files only, using FileFilter #7 Index file content #8
 * Index file name #9 Index file full path #10 Add document to Lucene index
 */